#ifndef PW_PBL_COROUTINE_IAWAITABLE_HPP
#define PW_PBL_COROUTINE_IAWAITABLE_HPP

#include <coroutine>

/// 协程名字空间
/// @note 本库的协程使用类似Javascript的单线程模型，多线程使用时各线程均可开启自己的协程执行器，
/// 但各线程的协程之间通信时需要另加同步机制，尤其注意co_await另一个线程的协程或等待器并不安全
namespace pw_pbl::co
{
	/// 获取协程执行器考虑各种配置项后最终选择的执行器实例，用户使用时建议使用executor()表示
	/// @note 最终实例与模板参数T的类型无关，模板参数T只用于延迟实例化
	template <typename T = void>
	inline consteval auto &executor();

	/// 执行器等待器接口的基类接口，执行器等待器接口必须派生自此类
	/// @sample struct IMP: public IAwaitable<IMP>
	template <typename IMP>
	struct IAwaitable
	{
		using ReadyFunc = bool(IMP &);

		std::coroutine_handle<> resume_handler; //< suspend时设置，resume后无效，有需要时可以在resume之前获取并清除
		ReadyFunc *ready_func;					//< 必须由具体实现类在构造时初始化

		inline void await_suspend(std::coroutine_handle<> hdl) noexcept
		{
			resume_handler = hdl;
			executor<IMP>().await_suspend(*static_cast<IMP *>(this));
		}

		inline bool virtual_ready() noexcept { return ready_func(*static_cast<IMP *>(this)); }

		inline void virtual_resume() noexcept { resume_handler.resume(); }

		IAwaitable() = default;

		IAwaitable(const IAwaitable &) = delete;
		IAwaitable(IAwaitable &&old) = default;

		IAwaitable &operator=(const IAwaitable &) = delete;
		IAwaitable &operator=(IAwaitable &&old) = delete;
	};

} // namespace pw_pbl::co

#endif // PW_PBL_COROUTINE_IAWAITABLE_HPP
